package org.jeecg.activiti.service.impl;

import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.UUID;
import java.util.stream.Collectors;

import javax.el.ExpressionFactory;
import javax.el.ValueExpression;

import org.activiti.bpmn.model.BpmnModel;
import org.activiti.bpmn.model.EndEvent;
import org.activiti.bpmn.model.ExclusiveGateway;
import org.activiti.bpmn.model.FlowElement;
import org.activiti.bpmn.model.FlowNode;
import org.activiti.bpmn.model.Gateway;
import org.activiti.bpmn.model.ParallelGateway;
import org.activiti.bpmn.model.Process;
import org.activiti.bpmn.model.SequenceFlow;
import org.activiti.bpmn.model.StartEvent;
import org.activiti.bpmn.model.SubProcess;
import org.activiti.bpmn.model.UserTask;
import org.activiti.engine.HistoryService;
import org.activiti.engine.RepositoryService;
import org.activiti.engine.RuntimeService;
import org.activiti.engine.TaskService;
import org.activiti.engine.history.HistoricActivityInstance;
import org.activiti.engine.history.HistoricProcessInstance;
import org.activiti.engine.history.HistoricProcessInstanceQuery;
import org.activiti.engine.history.HistoricTaskInstance;
import org.activiti.engine.repository.Model;
import org.activiti.engine.repository.ProcessDefinition;
import org.activiti.engine.runtime.Execution;
import org.activiti.engine.runtime.ExecutionQuery;
import org.activiti.engine.runtime.ProcessInstance;
import org.activiti.engine.runtime.ProcessInstanceQuery;
import org.activiti.engine.task.Task;
import org.activiti.engine.task.TaskQuery;
import org.apache.shiro.SecurityUtils;
import org.jeecg.activiti.entity.ActHiModelFormData;
import org.jeecg.activiti.entity.ActKAppendForm;
import org.jeecg.activiti.entity.ActKAppendFormData;
import org.jeecg.activiti.entity.ActKAppendFormDeployment;
import org.jeecg.activiti.entity.ActKHandleResult;
import org.jeecg.activiti.entity.ActKNode;
import org.jeecg.activiti.entity.ActKNodeFile;
import org.jeecg.activiti.entity.ActKProcessDuplicate;
import org.jeecg.activiti.entity.ActReModelExtend;
import org.jeecg.activiti.entity.ActReModelFormData;
import org.jeecg.activiti.entity.ActivitiConstant;
import org.jeecg.activiti.entity.ActivitiTaskVo;
import org.jeecg.activiti.mapper.ActReModelExtendMapper;
import org.jeecg.activiti.mapper.ActivitiTaskMapper;
import org.jeecg.activiti.service.IActHiModelFormDataService;
import org.jeecg.activiti.service.IActKAppendFormDataService;
import org.jeecg.activiti.service.IActKAppendFormDeploymentService;
import org.jeecg.activiti.service.IActKAppendFormService;
import org.jeecg.activiti.service.IActKHandleResultService;
import org.jeecg.activiti.service.IActKNodeFileService;
import org.jeecg.activiti.service.IActKNodeService;
import org.jeecg.activiti.service.IActKProcessDuplicateService;
import org.jeecg.activiti.service.IActReModelExtendService;
import org.jeecg.activiti.service.IActReModelFormDataService;
import org.jeecg.activiti.service.IActivitiTaskService;
import org.jeecg.common.api.dto.message.BusMessageDTO;
import org.jeecg.common.api.vo.Result;
import org.jeecg.common.system.api.ISysBaseAPI;
import org.jeecg.common.system.vo.LoginUser;
import org.jeecg.modules.online.cgform.entity.OnlCgformHead;
import org.jeecg.modules.online.cgform.service.IOnlCgformFieldService;
import org.jeecg.modules.online.cgform.service.IOnlCgformHeadService;
import org.jeecg.modules.online.cgform.util.SqlSymbolUtil;
import org.jeecg.modules.system.entity.SysUser;
import org.jeecg.modules.system.service.ISysRoleService;
import org.jeecg.modules.system.service.ISysUserService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;
import org.springframework.util.StringUtils;

import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.google.api.client.util.ArrayMap;
import com.google.api.client.util.Lists;
import com.googlecode.aviator.AviatorEvaluator;

import de.odysseus.el.ExpressionFactoryImpl;
import de.odysseus.el.util.SimpleContext;
import lombok.extern.slf4j.Slf4j;
import me.zhyd.oauth.log.Log;

/**
 * TODO
 *
 * @author dousw
 * @version 1.0
 * @date 2020/9/25 9:44
 */
@Slf4j
@Service
public class ActivitiTaskServiceImpl implements IActivitiTaskService {
	
	@Value("${jeecg.wx.bpmn.agentId}")
	private Integer agentId;

    @Autowired
    private RuntimeService runtimeService;

    @Autowired
    private RepositoryService repositoryService;

    @Autowired
    private HistoryService historyService;

    @Autowired
    private ISysUserService iSysUserService;

    @Autowired
    private TaskService taskService;
    
    @Autowired
    private IOnlCgformHeadService onlCgformHeadService;

    @Autowired
    private IActReModelFormDataService iActReModelFormDataService;

    @Autowired
    private IActKAppendFormService iActKAppendFormService;

    @Autowired
    private IActKNodeService iActKNodeService;

    @Autowired
    private IActKProcessDuplicateService iActKProcessDuplicateService;

    @Autowired
    private IActKAppendFormDeploymentService actKAppendFormDeploymentService;

    @Autowired
    private IActKHandleResultService iActKHandleResultService;

    @Autowired
    private IActKAppendFormDataService iActKAppendFormDataService;

    @Autowired
    private IActKNodeFileService iActKNodeFileService;

    @Autowired
    private ISysRoleService iSysRoleService;

    @Autowired
    private ISysBaseAPI iSysBaseAPI;
    
    @Autowired
    private ActivitiTaskMapper activitiTaskMapper;
    
    @Autowired
    private IOnlCgformFieldService fieldService;
    
    @Autowired
    private IActReModelExtendService actReModelExtendService;
    
    @Autowired
    private ActReModelExtendMapper actReModelExtendMapper;

    /**
     * 获取当前任务节点的下一个任务节点
     *
     * @param task 当前任务节点
     * @return 下个任务节点
     * @throws Exception
     */
    @Override
    public FlowElement getNextUserFlowElement(Task task) {
        // 取得已提交的任务
        HistoricTaskInstance historicTaskInstance = historyService.createHistoricTaskInstanceQuery()
                .taskId(task.getId()).singleResult();

        // 获得流程定义
        ProcessDefinition processDefinition = repositoryService.getProcessDefinition(historicTaskInstance.getProcessDefinitionId());

        //获得当前流程的活动ID
        ExecutionQuery executionQuery = runtimeService.createExecutionQuery();
        Execution execution = executionQuery.executionId(historicTaskInstance.getExecutionId()).singleResult();
        String activityId = execution.getActivityId();
        UserTask userTask = null;
        while (true) {
            //根据活动节点获取当前的组件信息
            FlowNode flowNode = getFlowNode(processDefinition.getId(), activityId);
            //获取该节点之后的流向
            List<SequenceFlow> sequenceFlowListOutGoing = flowNode.getOutgoingFlows();

            // 获取的下个节点不一定是userTask的任务节点，所以要判断是否是任务节点
            if (sequenceFlowListOutGoing.size() > 1) {
                // 如果有1条以上的出线，表示有分支，需要判断分支的条件才能知道走哪个分支
                // 遍历节点的出线得到下个activityId
                activityId = getNextActivityId(execution.getId(),
                        task.getProcessInstanceId(), sequenceFlowListOutGoing, null);
            } else if (sequenceFlowListOutGoing.size() == 1) {
                // 只有1条出线,直接取得下个节点
                SequenceFlow sequenceFlow = sequenceFlowListOutGoing.get(0);
                // 下个节点
                FlowElement flowElement = sequenceFlow.getTargetFlowElement();
                if (flowElement instanceof UserTask) {
                    // 下个节点为UserTask时
                    userTask = (UserTask) flowElement;
                    return userTask;
                } else if (flowElement instanceof ExclusiveGateway) {
                    // 下个节点为排它网关时
                    ExclusiveGateway exclusiveGateway = (ExclusiveGateway) flowElement;
                    List<SequenceFlow> outgoingFlows = exclusiveGateway.getOutgoingFlows();
                    // 遍历网关的出线得到下个activityId
                    activityId = getNextActivityId(execution.getId(), task.getProcessInstanceId(), outgoingFlows, null);
                }

            } else {
                // 没有出线，则表明是结束节点
                return null;
            }
        }

    }

    /**
     * 根据活动节点和流程定义ID获取该活动节点的组件信息
     */
    public FlowNode getFlowNode(String processDefinitionId, String flowElementId) {
        BpmnModel bpmnModel = repositoryService.getBpmnModel(processDefinitionId);
        FlowNode flowNode = (FlowNode) bpmnModel.getMainProcess().getFlowElement(flowElementId);
        return flowNode;
    }

    /**
     * 根据el表达式取得满足条件的下一个activityId
     * @param executionId
     * @param processInstanceId
     * @param outgoingFlows
     * @return
     */
    public String getNextActivityId(String executionId,
                                           String processInstanceId,
                                           List<SequenceFlow> outgoingFlows, Map<String, Object> transientVariables) {
        String activityId = null;
        // 遍历出线
        for (SequenceFlow outgoingFlow : outgoingFlows) {
            // 取得线上的条件
            String conditionExpression = outgoingFlow.getConditionExpression();
            // 取得所有变量
            Map<String, Object> variables = runtimeService.getVariables(executionId);

            if (!CollectionUtils.isEmpty(transientVariables)) {
                variables.putAll(transientVariables);
            }

            String variableName = "";
            // 判断网关条件里是否包含变量名
            for (String s : variables.keySet()) {
                if (conditionExpression.contains(s)) {
                    // 找到网关条件里的变量名
                    variableName = s;
                }
            }
            String conditionVal = getVariableValue(variableName, processInstanceId);
            // 判断el表达式是否成立
            if (isCondition(variableName, conditionExpression, conditionVal)) {
                // 取得目标节点
                FlowElement targetFlowElement = outgoingFlow.getTargetFlowElement();
                activityId = targetFlowElement.getId();
                continue;
            }
        }
        return activityId;
    }


    /**
     * 取得流程变量的值
     *
     * @param variableName      变量名
     * @param processInstanceId 流程实例Id
     * @return
     */
    public String getVariableValue(String variableName, String processInstanceId) {
        Execution execution = runtimeService
                .createExecutionQuery().processInstanceId(processInstanceId).list().get(0);
        Object object = runtimeService.getVariable(execution.getId(), variableName);
        return object == null ? "" : object.toString();
    }

    /**
     * 根据key和value判断el表达式是否通过
     *
     * @param key   el表达式key
     * @param el    el表达式
     * @param value el表达式传入值
     * @return
     */
    public static boolean isCondition(String key, String el, String value) {
        ExpressionFactory factory = new ExpressionFactoryImpl();
        SimpleContext context = new SimpleContext();
        context.setVariable(key, factory.createValueExpression(value, String.class));
        ValueExpression e = factory.createValueExpression(context, el, boolean.class);
        return (Boolean) e.getValue(context);
    }

    @Override
    public List<Map<String, Object>> getGroupTaskList(String modelKey, String modelName) {
        List<Map<String,Object>> resultList = new ArrayList<>();

        resultList.addAll(getCandidateUserTaskList(modelKey, modelName));

        return resultList;
    }

    @Override
    public void handelDuplicate(String usernames,String procInstId,String modelId,Task task, LoginUser sysUser) {
        if (!StringUtils.isEmpty(usernames)) {
            ProcessDefinition processDefinition = repositoryService.createProcessDefinitionQuery().processDefinitionId(task.getProcessDefinitionId()).singleResult();
            // ProcessInstance processInstance = runtimeService.createProcessInstanceQuery().processInstanceId(procInstId).singleResult();
            // String creator = iSysUserService.getUserByName(processInstance.getStartUserId()).getRealname();
            SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
            ActReModelFormData actReModelFormData = iActReModelFormDataService.getOne(new QueryWrapper<ActReModelFormData>().eq("process_instance_id", procInstId));
            Model model = repositoryService.createModelQuery().modelId(actReModelFormData.getModelId()).singleResult();

            String[] userArr = usernames.split(",");
            for (String username : userArr) {
                ActKProcessDuplicate actKProcessDuplicate = new ActKProcessDuplicate();
                actKProcessDuplicate.setCreateTime(new Date());
                actKProcessDuplicate.setCreateBy(sysUser.getUsername());

                actKProcessDuplicate.setModelId(actReModelFormData.getModelId());
                actKProcessDuplicate.setProcessInstanceId(procInstId);
                actKProcessDuplicate.setUsername(username);
                actKProcessDuplicate.setTaskId(task.getId());
                actKProcessDuplicate.setStartTime(simpleDateFormat.format(task.getCreateTime()));
                actKProcessDuplicate.setEndTime(simpleDateFormat.format(new Date()));
                actKProcessDuplicate.setUseTime(org.jeecg.activiti.util.StringUtils.getTimeDiff(task.getCreateTime(),new Date()));
                actKProcessDuplicate.setModelName(model.getName());
                actKProcessDuplicate.setModelKey(model.getKey());
                actKProcessDuplicate.setInitiator(actReModelFormData.getCreateBy());

                // SysUser user = iSysUserService.getUserByName(actReModelFormData.getCreateBy());
                // actKProcessDuplicate.setTitle(user.getRealname() + "发起了【" + model.getName() + "】申请");
                actKProcessDuplicate.setTitle(getInstanceName(actReModelFormData));

                iActKProcessDuplicateService.save(actKProcessDuplicate);

                String title = "【抄送】" + processDefinition.getName();
                String content = getInstanceName(actReModelFormData);
                // iSysBaseAPI.sendSysMsg(sysUser.getUsername(), username, content, content, task.getId(), "url", "/task/MyCcHisProcessList");
                BusMessageDTO msg = new BusMessageDTO();
                msg.setFromUser(sysUser.getUsername());
                msg.setToUser(username);
                msg.setTitle(title);
                msg.setContent(content);
                msg.setCategory("2");
                msg.setBusType("bpm");
                msg.setBusId(task.getId());
                msg.setThirdUrl("/approval");
                iSysBaseAPI.sendBusAnnouncement(msg);
                /*try{
                	WxCpService wxCpService =  WxCpConfiguration.getCpService(agentId);
            		WxCpMessageService wxCpMessageService = new WxCpMessageServiceImpl(wxCpService);
            		String url = wxCpService.getOauth2Service().buildAuthorizationUrl(wxCpService.getWxCpConfigStorage().getDomain()+"/approval",null);
            		LoginUser _user = iSysBaseAPI.getUserByName(username);
            		// WxCpMessage message = WxCpMessage.TEXTCARD().toUser(_user.getThirdId()).agentId(wxCpService.getWxCpConfigStorage().getAgentId()).title(user.getRealname() + "发起了【" + model.getName() + "】申请").description(content).url(url).build();
            		WxCpMessage message = WxCpMessage.TEXTCARD().toUser(_user.getThirdId()).agentId(wxCpService.getWxCpConfigStorage().getAgentId()).title(title).description(content).url(url).build();
            		wxCpMessageService.send(message);
                }catch (Exception e) {
				}*/
            }
        }
    }

    @Override
    public Map<String, Object> getMyTaskList(String modelName, String modelKey, String startUsername, Integer pageNo, Integer pageSize) {
        Map<String, Object> result = new HashMap<>();

        LoginUser sysUser = (LoginUser) SecurityUtils.getSubject().getPrincipal();

        List<Task> list = taskService.createTaskQuery()
                .taskAssignee(sysUser.getUsername()).orderByTaskCreateTime().desc()
                .list();
        List<Map<String,Object>> resultList = new ArrayList<>();
        for (Task task : list) {
            // 查询表单数据ID
            ActReModelFormData actReModelFormData = iActReModelFormDataService.getOne(new QueryWrapper<ActReModelFormData>().eq("process_instance_id", task.getProcessInstanceId()));
            if (actReModelFormData != null) {
                Map<String,Object> tempMap = new ArrayMap<>();

                // 流程名称/流程Key
                Model model = repositoryService.createModelQuery().modelId(actReModelFormData.getModelId()).singleResult();

                if (StringUtils.isEmpty(modelKey)
                        && StringUtils.isEmpty(modelName)
                        && StringUtils.isEmpty(startUsername)) {
                    handelTaskData(tempMap, task, actReModelFormData, model);

                    resultList.add(tempMap);
                } else if (!StringUtils.isEmpty(modelKey)
                        && StringUtils.isEmpty(modelName)
                        && StringUtils.isEmpty(startUsername)
                        && model.getKey().contains(modelKey)) {
                    handelTaskData(tempMap, task, actReModelFormData, model);

                    resultList.add(tempMap);
                } else if (StringUtils.isEmpty(modelKey)
                        && !StringUtils.isEmpty(modelName)
                        && StringUtils.isEmpty(startUsername)
                        && model.getName().contains(modelName)){
                    handelTaskData(tempMap, task, actReModelFormData, model);

                    resultList.add(tempMap);
                } else if (StringUtils.isEmpty(modelKey)
                        && StringUtils.isEmpty(modelName)
                        && !StringUtils.isEmpty(startUsername)
                        && startUsername.contains(actReModelFormData.getCreateBy())) {
                    handelTaskData(tempMap, task, actReModelFormData, model);

                    resultList.add(tempMap);
                } else if (!StringUtils.isEmpty(modelKey)
                        && !StringUtils.isEmpty(modelName)
                        && StringUtils.isEmpty(startUsername)
                        && model.getKey().contains(modelKey)
                        && model.getName().contains(modelName)) {
                    handelTaskData(tempMap, task, actReModelFormData, model);

                    resultList.add(tempMap);
                } else if (!StringUtils.isEmpty(modelKey)
                        && !StringUtils.isEmpty(modelName)
                        && !StringUtils.isEmpty(startUsername)
                        && model.getKey().contains(modelKey)
                        && model.getName().contains(modelName)
                        && startUsername.contains(actReModelFormData.getCreateBy())) {
                    handelTaskData(tempMap, task, actReModelFormData, model);

                    resultList.add(tempMap);
                }
            }
        }

        result.put("records", resultList);
        result.put("total", resultList.size());

        return result;
    }

    @Override
    public void saveActKAppendFormData(String taskId, String username, String formData, String appendFormId,
                                       String procInstId, String modelId, String nodeId, String appendFormDataId, String executionId) {
        if (!StringUtils.isEmpty(formData)) {
            ActKAppendFormData actKAppendFormData = new ActKAppendFormData();
            actKAppendFormData.setUsername(username);
            actKAppendFormData.setFormData(formData);
            actKAppendFormData.setFormId(appendFormId);
            actKAppendFormData.setProcessInstanceId(procInstId);
            actKAppendFormData.setModelId(modelId);
            actKAppendFormData.setNodeId(nodeId);
            actKAppendFormData.setCreateBy(username);
            actKAppendFormData.setCreateTime(new Date());
            actKAppendFormData.setExecutionId(executionId);
            actKAppendFormData.setTaskId(taskId);
            iActKAppendFormDataService.save(actKAppendFormData);
        }
    }

    @Override
    public void handleResult(String taskId, String procInstId, int flag, String comment, String taskDefinitionKey, String username, String executionId) {
        ActKHandleResult actKHandleResult = new ActKHandleResult();
        actKHandleResult.setProcessInstanceId(procInstId);
        actKHandleResult.setComment(comment);
        actKHandleResult.setNodeId(taskDefinitionKey);
        actKHandleResult.setTaskId(taskId);
        actKHandleResult.setCreateBy(username);
        actKHandleResult.setCreateTime(new Date());
        actKHandleResult.setExecutionId(executionId);
        if (flag == 0) {
            actKHandleResult.setResult(ActivitiConstant.HANDEL_RESULT_TY);
        } else if (flag == 1) {
            actKHandleResult.setResult(ActivitiConstant.HANDEL_RESULT_BTY);
        } else if (flag == 2){
            actKHandleResult.setResult(ActivitiConstant.HANDEL_RESULT_BH);
        } else if (flag == 5) {
            actKHandleResult.setResult(ActivitiConstant.HANDEL_RESULT_CX);
        } else if (flag == 6) {
            actKHandleResult.setResult(ActivitiConstant.HANDEL_RESULT_ZF);
        }

        iActKHandleResultService.save(actKHandleResult);
    }

    @Autowired
    private IActHiModelFormDataService iActHiModelFormDataService;

    @Override
    public boolean handleProcessStatus(String procInstId, String formDataId, int flag) {
        // 判断流程是否结束，如果结束更新流程状态
        ProcessInstanceQuery processInstance = runtimeService.createProcessInstanceQuery().processInstanceId(procInstId);
        ProcessInstance singleResult = processInstance.singleResult();
        if(singleResult==null){
            updateProcessStatus(flag == 1?ActivitiConstant.HANDLE_STATUS_WTG:ActivitiConstant.HANDLE_STATUS_YWC, procInstId);
            return true;
        }
        return false;
    }

    /**
     * 更新流程状态
     * @param status 状态码
     * @param procInstId 流程实例ID
     */
    public void updateProcessStatus(int status, String procInstId) {
        // 更新实时
        iActReModelFormDataService.update(new UpdateWrapper<ActReModelFormData>()
                .set("status", status)
                .eq("process_instance_id", procInstId));

        // 更新历史
        iActHiModelFormDataService.update(new UpdateWrapper<ActHiModelFormData>()
                .set("status", status)
                .eq("process_instance_id", procInstId));
    }

    // 存放正在执行的兄弟流程任务节点ID
    private static List<String> runningNodeIds = null;

    // 流程model
    private static BpmnModel bpmnModel = null;

    @Override
    @Transactional
    public Result<Object> rejectTargetNode(String taskId, String nodeId, String record, Map<String, Object> variables, Map<String, Object> transientVariables, LoginUser sysUser, String tableName) {
        // 驳回除发起人之外的任务节点
        Task task = taskService.createTaskQuery().taskId(taskId).singleResult();
        ActReModelFormData actReModelFormData = iActReModelFormDataService.getOne(new QueryWrapper<ActReModelFormData>().eq("process_instance_id", task.getProcessInstanceId()));

        if (nodeId.equals(ActivitiConstant.PROCESS_CREATOR_KEY)) {
            // 驳回到发起人

            runtimeService.deleteProcessInstance(task.getProcessInstanceId(), record);

            // 修改用户提交流程状态为已退回
            updateProcessStatus(ActivitiConstant.HANDLE_STATUS_YTH, task.getProcessInstanceId());
            if(tableName != null && !"".equals(tableName)){
            	this.fieldService.editFormBpmStatus(variables.get("id")+"", tableName, ActivitiConstant.HANDLE_STATUS_YTH+"");
            }

        } else if (nodeId.equals(ActivitiConstant.PROCESS_PREVIOUS_STEP_KEY)) {
            // 驳回上一步
            getPreOneIncomeNode(taskId);
        } else {
            // 驳回除发起人之外的任务节点

            String currActivitiId = task.getTaskDefinitionKey();
            String processDefinitionId = task.getProcessDefinitionId();

            bpmnModel = repositoryService.getBpmnModel(processDefinitionId);

            runningNodeIds = new ArrayList<>();

            // 处理驳回
            handleRejectTargetNode(bpmnModel, taskId, variables, currActivitiId, nodeId);

            // 推送消息
            ProcessInstance processInstance = runtimeService.createProcessInstanceQuery().processInstanceId(task.getProcessInstanceId()).singleResult();
            // String creator = iSysUserService.getUserByName(processInstance.getStartUserId()).getRealname();
            Task nextTask = taskService.createTaskQuery().processInstanceId(processInstance.getId()).taskDefinitionKey(nodeId).singleResult();
            // String content = sysUser.getRealname() + "驳回给您【"+ creator +"】提交的【" + bpmnModel.getMainProcess().getName() + "】申请，待审核！";
            // iSysBaseAPI.sendSysMsg(sysUser.getUsername(), nextTask.getAssignee(), content, content, task.getId(), "url", "/task/MyTaskList");
            String title = "【驳回】"+bpmnModel.getMainProcess().getName();
            String content = getInstanceName(actReModelFormData);
            BusMessageDTO msg = new BusMessageDTO();
            msg.setFromUser(sysUser.getUsername());
            msg.setToUser(nextTask.getAssignee());
            msg.setTitle(title);
            msg.setContent(content);
            msg.setCategory("2");
            msg.setBusType("bpm");
            msg.setBusId(task.getId());
            msg.setThirdUrl("/approval");
            iSysBaseAPI.sendBusAnnouncement(msg);
            System.out.println("taskId:" + taskId);
            /*try{
            	WxCpService wxCpService =  WxCpConfiguration.getCpService(agentId);
        		WxCpMessageService wxCpMessageService = new WxCpMessageServiceImpl(wxCpService);
        		String url = wxCpService.getOauth2Service().buildAuthorizationUrl(wxCpService.getWxCpConfigStorage().getDomain()+"/approval",null);
        		LoginUser _user = iSysBaseAPI.getUserByName(nextTask.getAssignee());
        		WxCpMessage message = WxCpMessage.TEXTCARD().toUser(_user.getThirdId()).agentId(wxCpService.getWxCpConfigStorage().getAgentId()).title(title).description(content).url(url).build();
        		wxCpMessageService.send(message);
            }catch (Exception e) {
			}*/

            // 处理兄弟流程驳回, 实现兄弟流程至结束流程
            handleRejectBrotherProcess(task.getProcessInstanceId(), currActivitiId, nodeId, bpmnModel, variables, record);

            // 修改用户提交流程状态为处理中
            updateProcessStatus(ActivitiConstant.HANDLE_STATUS_HLZ, task.getProcessInstanceId());
        }
        return Result.OK();
    }

    /**
     * 处理驳回目标节点
     * @param bpmnModel
     * @param taskId
     * @param variables
     * @param currActivitiId
     * @param targetActivitiId
     */
    public void handleRejectTargetNode(BpmnModel bpmnModel, String taskId, Map<String, Object> variables, String currActivitiId, String targetActivitiId) {
        FlowNode currFlow = (FlowNode)bpmnModel.getMainProcess().getFlowElement(currActivitiId);
        if (currFlow == null) {
            List<SubProcess> subProcessList = bpmnModel.getMainProcess().findFlowElementsOfType(SubProcess.class, true);
            for (SubProcess subProcess : subProcessList) {
                FlowElement flowElement = subProcess.getFlowElement(currActivitiId);

                if (flowElement != null) {
                    currFlow = (FlowNode) flowElement;
                    break;
                }
            }
        }

        // 获取目标节点
        FlowNode target = (FlowNode)bpmnModel.getFlowElement(targetActivitiId);

        //如果不是同一个流程（子流程）不能驳回
        if (!(currFlow.getParentContainer().equals(target.getParentContainer()))) {
            Log.error("不是同一个流程（子流程）不能驳回！");
        } else {
            // 记录原活动方向
            List<SequenceFlow> oriSequenceFlows = Lists.newArrayList();
            oriSequenceFlows.addAll(currFlow.getOutgoingFlows());

            // 清理活动方向
            currFlow.getOutgoingFlows().clear();

            // 建立新方向
            List<SequenceFlow> newSequenceFlows = Lists.newArrayList();
            SequenceFlow newSequenceFlow = new SequenceFlow();
            String uuid = UUID.randomUUID().toString().replace("-","");
            newSequenceFlow.setId(uuid);
            newSequenceFlow.setSourceFlowElement(currFlow);// 原节点
            newSequenceFlow.setTargetFlowElement(target);// 目标节点
            newSequenceFlows.add(newSequenceFlow);
            currFlow.setOutgoingFlows(newSequenceFlows);

            // 拒接、通过、驳回指定节点
            taskService.setVariables(taskId, variables);
            taskService.complete(taskId);

            //恢复原方向
            currFlow.setOutgoingFlows(oriSequenceFlows);
        }
    }

    /**
     * 处理兄弟流程至结束任务节点
     * @param proInsId
     * @param currActivitiId
     * @param targetActivitiId
     * @param bpmnModel
     * @param variables
     */
    public void handleRejectBrotherProcess(String proInsId, String currActivitiId, String targetActivitiId,
                                           BpmnModel bpmnModel, Map<String, Object> variables, String comment) {
        // 处理消息
        ProcessInstance processInstance = runtimeService.createProcessInstanceQuery().processInstanceId(proInsId).singleResult();
        // String creator = iSysUserService.getUserByName(processInstance.getStartUserId()).getRealname();
        ActReModelFormData actReModelFormData = iActReModelFormDataService.getOne(new QueryWrapper<ActReModelFormData>().eq("process_instance_id", processInstance.getId()));
        LoginUser sysUser = (LoginUser) SecurityUtils.getSubject().getPrincipal();

        // 组装处理意见
        FlowElement targetFlowElement = bpmnModel.getMainProcess().getFlowElement(targetActivitiId);
        String record = sysUser.getRealname() + "退回至" + targetFlowElement.getName();

        //消息内容
        // String content = sysUser.getRealname() + "将【"+ creator +"】提交的【" + bpmnModel.getMainProcess().getName() + "】申请驳回到" +  targetFlowElement.getName() + "了！";
        String title = "【退回】"+bpmnModel.getMainProcess().getName();
        String content = getInstanceName(actReModelFormData);
        
        List<Execution> brotherExecutions = getRunningBrotherProcessNode(proInsId, currActivitiId, targetActivitiId);

        String endNodeId = "";
        List<FlowElement> flowElements = (List<FlowElement>)bpmnModel.getMainProcess().getFlowElements();
        for (FlowElement flowElement : flowElements) {
            if (flowElement instanceof EndEvent) {
                endNodeId = flowElement.getId();
            }
        }
        String finalEndNodeId = endNodeId;
        brotherExecutions.forEach(execution -> {
            String nodeId = execution.getActivityId();
            if (runningNodeIds.contains(nodeId)) {
                Task tempTask = taskService.createTaskQuery().executionId(execution.getId()).singleResult();
                if (tempTask != null) {
                    handleRejectTargetNode(bpmnModel, tempTask.getId(), variables, execution.getActivityId(), finalEndNodeId);

                    // 处理意见
                    handleResult(tempTask.getId(), proInsId, 2, record, tempTask.getTaskDefinitionKey(), sysUser.getUsername(), execution.getId());

                    // 发送消息
                    // iSysBaseAPI.sendSysMsg(sysUser.getUsername(), tempTask.getAssignee(), content, content, tempTask.getId(), "url", "/task/MyTaskList");
                    
                    BusMessageDTO msg = new BusMessageDTO();
                    msg.setFromUser(sysUser.getUsername());
                    msg.setToUser(tempTask.getAssignee());
                    msg.setTitle(title);
                    msg.setContent(content);
                    msg.setCategory("2");
                    msg.setBusType("bpm");
                    msg.setBusId(tempTask.getId());
                    msg.setThirdUrl("/approval");
                    iSysBaseAPI.sendBusAnnouncement(msg);
                    System.out.println(tempTask.getId());
                    /*try{
                    	WxCpService wxCpService =  WxCpConfiguration.getCpService(agentId);
                		WxCpMessageService wxCpMessageService = new WxCpMessageServiceImpl(wxCpService);
                		String url = wxCpService.getOauth2Service().buildAuthorizationUrl(wxCpService.getWxCpConfigStorage().getDomain()+"/approval",null);
                		LoginUser _user = iSysBaseAPI.getUserByName(tempTask.getAssignee());
                		WxCpMessage message = WxCpMessage.TEXTCARD().toUser(_user.getThirdId()).agentId(wxCpService.getWxCpConfigStorage().getAgentId()).title(title).description(content).url(url).build();
                		wxCpMessageService.send(message);
                    }catch (Exception e) {
        			}*/
                }
            }
        });
    }

    /**
     * 获取兄弟流程节点
     * @param processInstanceId 流程实例ID
     * @param currActivitiId 当前任务节点ID
     * @param targetActivitiId 目标任务节点ID
     * @return
     */
    public List<Execution> getRunningBrotherProcessNode(String processInstanceId, String currActivitiId, String targetActivitiId) {

        // 根据实例ID查询进行中的执行任务，并排除当前任务节点、目标任务节点的执行任务
        List<Execution> executionList = runtimeService.createExecutionQuery()
                .processInstanceId(processInstanceId)
                .list()
                .stream()
                .filter(execution -> !StringUtils.isEmpty(execution.getActivityId()) && !execution.getActivityId().equals(currActivitiId) && !execution.getActivityId().equals(targetActivitiId))
                .collect(Collectors.toList());

        // 根据正在执行的任务节点判断是否是目标任务节点的兄弟子流程，如果是流程结束，如果不是流程继续执行
        FlowNode currFlow = (FlowNode)bpmnModel.getMainProcess().getFlowElement(targetActivitiId);
        List<SequenceFlow> outgoingFlows = currFlow.getOutgoingFlows();

        executionList.forEach(execution -> {
            String nodeId = execution.getActivityId();
            handelBpmn(outgoingFlows, nodeId);
        });

        return executionList;
    }

    /**
     * 获取与驳回任务节点在一条线上运行中的任务节点ID
      */
    public void handelBpmn(List<SequenceFlow> outgoingFlows, String endActivityId) {
        for (SequenceFlow outgoingFlow : outgoingFlows) {
            String targetNodeId = outgoingFlow.getTargetRef();
            FlowNode targetFlowNode = (FlowNode)bpmnModel.getMainProcess().getFlowElement(targetNodeId);
            if (targetNodeId.equals(endActivityId)) {
                runningNodeIds.add(targetNodeId);
                break;
            } else {
                handelBpmn(targetFlowNode.getOutgoingFlows(), endActivityId);
            }
        }
    }

    @Override
    public void handleCancellation(String procInstId) {
        LoginUser sysUser = (LoginUser) SecurityUtils.getSubject().getPrincipal();

        // 获取当前执行任务节点
        ProcessInstance processInstance = runtimeService.createProcessInstanceQuery().processInstanceId(procInstId).singleResult();
        List<Execution> list = runtimeService.createExecutionQuery().processInstanceId(processInstance.getId()).list();
        Set<Execution> executions = list.stream().filter(execution -> execution.getActivityId() != null).collect(Collectors.toSet());
        ActReModelFormData actReModelFormData = iActReModelFormDataService.getOne(new QueryWrapper<ActReModelFormData>().eq("process_instance_id", procInstId));
        Iterator<Execution> iterator = executions.iterator();
        while (iterator.hasNext()) {
            Execution execution = iterator.next();
            // 获取当前执行任务
            Task task = taskService.createTaskQuery().executionId(execution.getId()).singleResult();
            // String comment = "【" + sysUser.getRealname() + "】作废了【"+processInstance.getProcessDefinitionName()+"】申请";
            String title = "【作废】"+processInstance.getProcessDefinitionName();
            String content = getInstanceName(actReModelFormData);
            handleResult(task.getId(), procInstId, ActivitiConstant.HANDLE_STATUS_YZF, content, task.getTaskDefinitionKey(), sysUser.getUsername(), execution.getId());
            
            BusMessageDTO msg = new BusMessageDTO();
            msg.setFromUser(sysUser.getUsername());
            msg.setToUser(task.getAssignee());
            msg.setTitle(title);
            msg.setContent(content);
            msg.setCategory("2");
            msg.setBusType("bpm");
            msg.setBusId(task.getId());
            msg.setThirdUrl("/approval");
            iSysBaseAPI.sendBusAnnouncement(msg);
            System.out.println(task.getId());
            /*try{
            	WxCpService wxCpService =  WxCpConfiguration.getCpService(agentId);
        		WxCpMessageService wxCpMessageService = new WxCpMessageServiceImpl(wxCpService);
        		String url = wxCpService.getOauth2Service().buildAuthorizationUrl(wxCpService.getWxCpConfigStorage().getDomain()+"/approval",null);
        		LoginUser _user = iSysBaseAPI.getUserByName(task.getAssignee());
        		WxCpMessage message = WxCpMessage.TEXTCARD().toUser(_user.getThirdId()).agentId(wxCpService.getWxCpConfigStorage().getAgentId()).title(title).description(content).url(url).build();
        		wxCpMessageService.send(message);
            }catch (Exception e) {
    		}*/
        }

        runtimeService.deleteProcessInstance(procInstId, ActivitiConstant.HANDEL_RESULT_ZF);

        // 修改用户提交流程状态为已作废
        updateProcessStatus(ActivitiConstant.HANDLE_STATUS_YZF, procInstId);
        
    }

    @Override
    public void handleCompleteTask(String taskId, String procInstId, String comment, Map<String, Object> variables, Map<String, Object> transientVariables, Task task, ActReModelFormData actReModelFormData) {
        String fromUser = task.getAssignee();
        String executeId = task.getExecutionId();
        String processDefinitionId = task.getProcessDefinitionId();

        /*//处理Onl主表更新数据
        
        Map<String, Object> processVariables = task.getProcessVariables();
		Map<String, Object> updateMap = new HashMap<>();
		for(Iterator<Map.Entry<String,Object>> iterator = transientVariables.entrySet().iterator(); iterator.hasNext();){
			Entry<String,Object> entry = iterator.next();
			if(variables.containsKey(entry.getKey()) && !"bpm_status".equals(entry.getKey()) && !"flag".equals(entry.getKey())){
				updateMap.put(entry.getKey(), entry.getValue());
			}
		}
		//Onl主表数据执行更新
		if((int)variables.get("flag") != 2 && !updateMap.isEmpty()){
			actReModelFormData.setFormData(JSONObject.toJSONString(variables));
			iActReModelFormDataService.updateById(actReModelFormData);
			if(actReModelFormData.getTableName() != null && !"".equals(actReModelFormData.getTableName())){
				String recordId = variables.get("id")+"";
				fieldService.editFormData(recordId, actReModelFormData.getTableName(), updateMap);
			}
		}
		
		transientVariables.putAll(variables);*/
		
        taskService.addComment(taskId, procInstId, comment == null ? "" : comment);
        taskService.setVariables(taskId, variables);
        taskService.complete(taskId);

        handleCompleteTaskSendMsg(fromUser, executeId, procInstId, processDefinitionId);
    }

    /**
     * 处理完成任务向下个任务节点发送待办消息
     * @param fromUser
     * @param executeId
     */
    public void handleCompleteTaskSendMsg(String fromUser, String executeId, String procInstId, String processDefinitionId) {
        ProcessDefinition processDefinition = repositoryService.createProcessDefinitionQuery().processDefinitionId(processDefinitionId).singleResult();
        ProcessInstance processInstance = runtimeService.createProcessInstanceQuery().processInstanceId(procInstId).singleResult();
        ActReModelFormData actReModelFormData = iActReModelFormDataService.getOne(new QueryWrapper<ActReModelFormData>().eq("process_instance_id", procInstId));
        if (processInstance == null) {
            HistoricProcessInstance historicProcessInstance = historyService.createHistoricProcessInstanceQuery().processInstanceId(procInstId).singleResult();
            String toUser = historicProcessInstance.getStartUserId();
            // String content = "你发起的【" + processDefinition.getName() + "】申请已审批完成！";
            // iSysBaseAPI.sendSysMsg(fromUser, toUser, content, content, procInstId, "url", "/process/ExtActDesignFlowDataList");
            String title = "【完成】"+processDefinition.getName();
            String content = getInstanceName(actReModelFormData);
            BusMessageDTO msg = new BusMessageDTO();
            msg.setFromUser(fromUser);
            msg.setToUser(toUser);
            msg.setTitle(title);
            msg.setContent(content);
            msg.setCategory("2");
            msg.setBusType("bpm2");
            msg.setBusId(procInstId);
            msg.setThirdUrl("/approval");
            iSysBaseAPI.sendBusAnnouncement(msg);
            /*try{
            	WxCpService wxCpService =  WxCpConfiguration.getCpService(agentId);
        		WxCpMessageService wxCpMessageService = new WxCpMessageServiceImpl(wxCpService);
        		String url = wxCpService.getOauth2Service().buildAuthorizationUrl(wxCpService.getWxCpConfigStorage().getDomain()+"/approval",null);
        		LoginUser _user = iSysBaseAPI.getUserByName(toUser);
        		WxCpMessage message = WxCpMessage.TEXTCARD().toUser(_user.getThirdId()).agentId(wxCpService.getWxCpConfigStorage().getAgentId()).title(title).description(content).url(url).build();
        		wxCpMessageService.send(message);
            }catch (Exception e) {
			}*/
        } else {
            // String proInsCreateUser = iSysUserService.getUserByName(processInstance.getStartUserId()).getRealname();

            List<Task> tasks = taskService.createTaskQuery().executionId(executeId).list();
            tasks.forEach(item -> {
                String toUser = item.getAssignee();

                if (!StringUtils.isEmpty(toUser)) {
                    // String content = proInsCreateUser + "提交的【" + processDefinition.getName() + "】申请待您审核！";
                	String title = "【审核】"+ processDefinition.getName();
                    String content = getInstanceName(actReModelFormData);
                    // iSysBaseAPI.sendSysMsg(fromUser, toUser, content, content, item.getId(), "url", "/task/MyTaskList");
                    BusMessageDTO msg = new BusMessageDTO();
                    msg.setFromUser(fromUser);
                    msg.setToUser(toUser);
                    msg.setTitle(title);
                    msg.setContent(content);
                    msg.setCategory("2");
                    msg.setBusType("bpm");
                    msg.setBusId(item.getId());
                    msg.setThirdUrl("/approval");
                    iSysBaseAPI.sendBusAnnouncement(msg);
                    System.out.println(item.getId());
                    /*try{
                    	WxCpService wxCpService =  WxCpConfiguration.getCpService(agentId);
                		WxCpMessageService wxCpMessageService = new WxCpMessageServiceImpl(wxCpService);
                		String url = wxCpService.getOauth2Service().buildAuthorizationUrl(wxCpService.getWxCpConfigStorage().getDomain()+"/approval",null);
                		LoginUser _user = iSysBaseAPI.getUserByName(toUser);
                		WxCpMessage message = WxCpMessage.TEXTCARD().toUser(_user.getThirdId()).agentId(wxCpService.getWxCpConfigStorage().getAgentId()).title(title).description(content).url(url).build();
                		wxCpMessageService.send(message);
                    }catch (Exception e) {
        			}*/
                } else {
                    BpmnModel model = repositoryService.getBpmnModel(processDefinitionId);
                    // String content = proInsCreateUser + "提交的【" + processDefinition.getName() + "】申请待您拾取！";
                    String title = "【拾取】"+ processDefinition.getName();
                    String content = getInstanceName(actReModelFormData);
                    // 获取流程节点审批人
                    UserTask userTask = (UserTask) model.getMainProcess().getFlowElement(item.getTaskDefinitionKey());
                    List<String> candidateUsers = userTask.getCandidateUsers();
                    if (!CollectionUtils.isEmpty(candidateUsers)) {
                        String userStr = String.join(",", candidateUsers);
                        // iSysBaseAPI.sendSysMsg(fromUser, userStr, content, content, item.getId(), "url", "/task/MyTaskList");
                        BusMessageDTO msg = new BusMessageDTO();
                        msg.setFromUser(fromUser);
                        msg.setToUser(userStr);
                        msg.setTitle(title);
                        msg.setContent(content);
                        msg.setCategory("2");
                        msg.setBusType("bpm");
                        msg.setBusId(item.getId());
                        msg.setThirdUrl("/approval");
                        iSysBaseAPI.sendBusAnnouncement(msg);
                        /*try{
		                	WxCpService wxCpService =  WxCpConfiguration.getCpService(agentId);
		            		WxCpMessageService wxCpMessageService = new WxCpMessageServiceImpl(wxCpService);
		            		String url = wxCpService.getOauth2Service().buildAuthorizationUrl(wxCpService.getWxCpConfigStorage().getDomain()+"/approval",null);
		            		List<String> wxCandidateUsers = new ArrayList<>();
		            		for(String candidateUser : candidateUsers){
		            			LoginUser _user = iSysBaseAPI.getUserByName(candidateUser);
		            			if(_user != null){
		            				wxCandidateUsers.add(_user.getThirdId());
		            			}
		            		}
		            		String wxUser = String.join("|", wxCandidateUsers);
		            		WxCpMessage message = WxCpMessage.TEXTCARD().toUser(wxUser).agentId(wxCpService.getWxCpConfigStorage().getAgentId()).title(title).description(content).url(url).build();
		            		wxCpMessageService.send(message);
		                }catch (Exception e) {
		    			}*/
                        
                    } else {
                        List<String> candidateGroups = userTask.getCandidateGroups();
                        if (!CollectionUtils.isEmpty(candidateGroups)) {
                            for (String role : candidateGroups) {
                                List<String> userIds = iSysRoleService.getUsersByRoleCode(role).stream().map(SysUser::getUsername).collect(Collectors.toList());
                                String userStr = String.join(",", userIds);
                                // iSysBaseAPI.sendSysMsg(fromUser, userStr, content, content, item.getId(), "url", "/task/MyTaskList");
                                BusMessageDTO msg = new BusMessageDTO();
				                msg.setFromUser(fromUser);
				                msg.setToUser(userStr);
				                msg.setTitle(title);
				                msg.setContent(content);
				                msg.setCategory("2");
				                msg.setBusType("bpm");
				                msg.setBusId(item.getId());
				                msg.setThirdUrl("/approval");
				                iSysBaseAPI.sendBusAnnouncement(msg);
				                System.out.println(item.getId());
				                /*try{
				                	WxCpService wxCpService =  WxCpConfiguration.getCpService(agentId);
				            		WxCpMessageService wxCpMessageService = new WxCpMessageServiceImpl(wxCpService);
				            		String url = wxCpService.getOauth2Service().buildAuthorizationUrl(wxCpService.getWxCpConfigStorage().getDomain()+"/approval",null);
				            		
				            		List<String> wxUsernames = new ArrayList<>();
				            		for(String username : userIds){
				            			LoginUser _user = iSysBaseAPI.getUserByName(username);
				            			if(_user != null){
				            				wxUsernames.add(_user.getThirdId());
				            			}
				            		}
				            		String wxUser = String.join("|", wxUsernames);
				            		WxCpMessage message = WxCpMessage.TEXTCARD().toUser(wxUser).agentId(wxCpService.getWxCpConfigStorage().getAgentId()).title(title).description(content).url(url).build();
				            		wxCpMessageService.send(message);
				                }catch (Exception e) {
				    			}*/
                            }
                        }
                    }
                }
            });
        }
    }

    @Override
    public void saveFiles(Task myTask, String procInstId, String files, String username) {
        if (!StringUtils.isEmpty(files)) {
            List<ActKNodeFile> actKNodeFiles = new ArrayList<>();

            String[] fileArr = files.split(",");
            for (String file : fileArr) {
                ActKNodeFile actKNodeFile = new ActKNodeFile();
                actKNodeFile.setFilePath(file);
                actKNodeFile.setProcessInstanceId(procInstId);
                actKNodeFile.setNodeId(myTask.getTaskDefinitionKey());
                actKNodeFile.setTaskId(myTask.getId());
                actKNodeFile.setExecutionId(myTask.getExecutionId());
                actKNodeFile.setCreateBy(username);
                actKNodeFile.setCreateTime(new Date());

                actKNodeFiles.add(actKNodeFile);
            }

            iActKNodeFileService.saveBatch(actKNodeFiles);
        }
    }

    @Override
    public void revocation(String procInstId) {
        LoginUser sysUser = (LoginUser) SecurityUtils.getSubject().getPrincipal();

        // 获取当前执行任务节点
        ProcessInstance processInstance = runtimeService.createProcessInstanceQuery().processInstanceId(procInstId).singleResult();
        List<Execution> list = runtimeService.createExecutionQuery().processInstanceId(processInstance.getId()).list();
        Set<Execution> executions = list.stream().filter(execution -> execution.getActivityId() != null).collect(Collectors.toSet());
        ActReModelFormData actReModelFormData = iActReModelFormDataService.getOne(new QueryWrapper<ActReModelFormData>().eq("process_instance_id", procInstId));
        Iterator<Execution> iterator = executions.iterator();
        while (iterator.hasNext()) {
            Execution execution = iterator.next();
            // 获取当前执行任务
            Task task = taskService.createTaskQuery().executionId(execution.getId()).singleResult();
            // String comment = "【" + sysUser.getRealname() + "】追回了【"+ processInstance.getProcessDefinitionName() +"】申请";
            String title = "【追回】"+ processInstance.getProcessDefinitionName();
            String content = getInstanceName(actReModelFormData);
            handleResult(task.getId(), procInstId, ActivitiConstant.HANDLE_STATUS_YCX, title, task.getTaskDefinitionKey(), sysUser.getUsername(), execution.getId());
            
            BusMessageDTO msg = new BusMessageDTO();
            msg.setFromUser(sysUser.getUsername());
            msg.setToUser(task.getAssignee());
            msg.setTitle(title);
            msg.setContent(content);
            msg.setCategory("2");
            msg.setBusType("bpm");
            msg.setBusId(task.getId());
            msg.setThirdUrl("/approval");
            iSysBaseAPI.sendBusAnnouncement(msg);
            System.out.println(task.getId());
            /*try{
            	WxCpService wxCpService =  WxCpConfiguration.getCpService(agentId);
        		WxCpMessageService wxCpMessageService = new WxCpMessageServiceImpl(wxCpService);
        		String url = wxCpService.getOauth2Service().buildAuthorizationUrl(wxCpService.getWxCpConfigStorage().getDomain()+"/approval",null);
        		LoginUser _user = iSysBaseAPI.getUserByName(task.getAssignee());
        		WxCpMessage message = WxCpMessage.TEXTCARD().toUser(_user.getThirdId()).agentId(wxCpService.getWxCpConfigStorage().getAgentId()).title(title).description(content).url(url).build();
        		wxCpMessageService.send(message);
            }catch (Exception e) {
			}*/
        }

        runtimeService.deleteProcessInstance(procInstId, ActivitiConstant.HANDEL_RESULT_CX);

        // 修改用户提交流程状态为已撤回
        updateProcessStatus(ActivitiConstant.HANDLE_STATUS_YCX, procInstId);
    }

    @Override
    public void backProcess(String taskId) {
        Task curTask = taskService.createTaskQuery().taskId(taskId).singleResult();

        String processInstanceId = curTask.getProcessInstanceId();
        List<HistoricTaskInstance> htiList = historyService.createHistoricTaskInstanceQuery()
                .processInstanceId(processInstanceId).orderByHistoricTaskInstanceStartTime().desc().list();

        if (CollectionUtils.isEmpty(htiList) || htiList.size() < 2) {
            return;
        }

        // list里的第二条代表上一个任务
        HistoricTaskInstance lastTask = htiList.get(1);

        // list里的第二条代表当前任务
        HistoricTaskInstance currTask = htiList.get(0);

        // 当前节点的executionId
        String curExecutionId = currTask.getExecutionId();

        // 上个节点的taskId
        String lastTaskId = lastTask.getId();

        // 上个节点的executionId
        String lastExecutionId = lastTask.getExecutionId();

        if (StringUtils.isEmpty(lastTaskId)) {
            Log.error("LAST TASK IS NULL");
            return;
        }

        String processDefinitionId = lastTask.getProcessDefinitionId();
        BpmnModel bpmnModel = repositoryService.getBpmnModel(processDefinitionId);

        String lastActivityId = null;
        List<HistoricActivityInstance> haiFinishedList = historyService.createHistoricActivityInstanceQuery().executionId(lastExecutionId).finished().list();

        for (HistoricActivityInstance hai : haiFinishedList) {
            if (lastTaskId.equals(hai.getTaskId())) {
                // 得到activityId, 只有historicActivityInstance对象里才有此方法
                lastActivityId = hai.getActivityId();
                break;
            }
        }

        // 得到上个节点的信息
        FlowNode lastFlowNode = (FlowNode)bpmnModel.getMainProcess().getFlowElement(lastActivityId);

        // 获取当前节点的信息
        Execution execution = runtimeService.createExecutionQuery().executionId(curExecutionId).singleResult();
        String curActivityId = execution.getActivityId();
        FlowNode curFlowNode = (FlowNode)bpmnModel.getMainProcess().getFlowElement(curActivityId);

        // 记录当前节点的原始活动时间
        List<SequenceFlow> oriSequenceFlows = new ArrayList<>();
        oriSequenceFlows.addAll(curFlowNode.getOutgoingFlows());

        // 清理活动方向
        curFlowNode.getOutgoingFlows().clear();

        // 建立新方向
        List<SequenceFlow> newSequenceFlowList = new ArrayList<>();
        SequenceFlow newSequenceFlow = new SequenceFlow();
        newSequenceFlow.setId("newSequenceFlowId");
        newSequenceFlow.setSourceFlowElement(curFlowNode);
        newSequenceFlow.setTargetFlowElement(lastFlowNode);
        newSequenceFlowList.add(newSequenceFlow);
        curFlowNode.setOutgoingFlows(newSequenceFlowList);

        // 完成任务
        taskService.complete(curTask.getId());

        // 恢复原方向
        curFlowNode.setOutgoingFlows(oriSequenceFlows);

        Task nextTask = taskService.createTaskQuery().processInstanceId(processInstanceId).singleResult();

        // 设置执行人
        if (nextTask != null) {
            taskService.setAssignee(nextTask.getId(), lastTask.getAssignee());
        }
    }

    public void getPreOneIncomeNode(String taskId) {
        List<Map<String, String>> incomeNodes = new ArrayList<>();

        Task task = taskService.createTaskQuery().taskId(taskId).singleResult();
        String currActivityId = task.getTaskDefinitionKey();

        // 获取当前用户任务节点
        BpmnModel bpmnModel = repositoryService.getBpmnModel(task.getProcessDefinitionId());
        Process process = bpmnModel.getProcesses().get(0);

        getIncomeNodesRecur(currActivityId, incomeNodes, process, false);

        FlowNode currFlow = (FlowNode)bpmnModel.getMainProcess().getFlowElement(currActivityId);
        if (currFlow == null) {
            List<SubProcess> subProcessList = bpmnModel.getMainProcess().findFlowElementsOfType(SubProcess.class, true);
            for (SubProcess subProcess : subProcessList) {
                FlowElement flowElement = subProcess.getFlowElement(currActivityId);

                if (flowElement != null) {
                    currFlow = (FlowNode) flowElement;
                    break;
                }
            }
        }

        // 记录原活动方向
        List<SequenceFlow> oriSequenceFlows = Lists.newArrayList();
        oriSequenceFlows.addAll(currFlow.getOutgoingFlows());

        // 清理活动方向
        currFlow.getOutgoingFlows().clear();

        List<SequenceFlow> newSequenceFlows = Lists.newArrayList();

        for (int i = 0; i< incomeNodes.size(); i++) {
            Map<String, String> item = incomeNodes.get(i);
            String nodeId = item.get("id");

            // 获取目标节点
            FlowNode target = (FlowNode)bpmnModel.getFlowElement(nodeId);

            //如果不是同一个流程（子流程）不能驳回
            if (!(currFlow.getParentContainer().equals(target.getParentContainer()))) {
                continue;
            }

            // 建立新方向
            SequenceFlow newSequenceFlow = new SequenceFlow();
            String uuid = UUID.randomUUID().toString().replace("-","");
            newSequenceFlow.setId(uuid);
            newSequenceFlow.setSourceFlowElement(currFlow);// 原节点
            newSequenceFlow.setTargetFlowElement(target);// 目标节点
            newSequenceFlows.add(newSequenceFlow);
        };

        currFlow.setOutgoingFlows(newSequenceFlows);

        // 拒接、通过、驳回指定节点
        taskService.complete(taskId);

        // 修改用户提交流程状态为处理中
        updateProcessStatus(ActivitiConstant.HANDLE_STATUS_HLZ, task.getProcessInstanceId());

        //恢复原方向
        currFlow.setOutgoingFlows(oriSequenceFlows);
    }

    public void getIncomeNodesRecur(String currentNodeId, List<Map<String, String>> incomeNodes, Process process, boolean isAll) {
        FlowElement currentFlowElement = process.getFlowElement(currentNodeId);
        List<SequenceFlow> incomingFlows = null;
        if (currentFlowElement instanceof UserTask) {
            incomingFlows = ((UserTask) currentFlowElement).getIncomingFlows();
        } else if (currentFlowElement instanceof Gateway) {
            incomingFlows = ((Gateway) currentFlowElement).getIncomingFlows();
        } else if (currentFlowElement instanceof StartEvent) {
            incomingFlows = ((StartEvent) currentFlowElement).getIncomingFlows();
        }
        if (incomingFlows != null && incomingFlows.size() > 0) {
            incomingFlows.forEach(incomingFlow -> {
                // String expression = incomingFlow.getConditionExpression();
                // 出线的上一节点
                String sourceFlowElementID = incomingFlow.getSourceRef();
                // 查询上一节点的信息
                FlowElement preFlowElement = process.getFlowElement(sourceFlowElementID);

                //用户任务
                if (preFlowElement instanceof UserTask) {
                    Map<String,String> tempMap = new HashMap<>();
                    tempMap.put("id", preFlowElement.getId());
                    tempMap.put("name", preFlowElement.getName());
                    incomeNodes.add(tempMap);
                    if (isAll) {
                        getIncomeNodesRecur(preFlowElement.getId(), incomeNodes, process, true);
                    }
                }
                //排他网关
                else if (preFlowElement instanceof ExclusiveGateway) {
                    getIncomeNodesRecur(preFlowElement.getId(), incomeNodes, process, isAll);
                }
                //并行网关
                else if (preFlowElement instanceof ParallelGateway) {
                    getIncomeNodesRecur(preFlowElement.getId(), incomeNodes, process, isAll);
                }
            });
        }
    }

    @Override
    public List<Map<String, Object>> getMyCreateTask(String processInstanceId, String active) {
        LoginUser sysUser = (LoginUser) SecurityUtils.getSubject().getPrincipal();
        HistoricProcessInstanceQuery query = historyService.createHistoricProcessInstanceQuery();
        if(!StringUtils.isEmpty(processInstanceId)){
        	query.processInstanceId(processInstanceId);
        }
        if(!StringUtils.isEmpty(active)){
        	if("0".equals(active)){
        		query.finished();
            }else {
            	query.unfinished();
            }
        }
        
        List<HistoricProcessInstance> historicProcessInstanceList = query
                .startedBy(sysUser.getUsername()).orderByProcessInstanceStartTime().desc().list();

        List<Map<String,Object>> resultList = new ArrayList<>();

        historicProcessInstanceList.forEach(item -> {
            ProcessDefinition processDefinition = repositoryService.createProcessDefinitionQuery().processDefinitionId(item.getProcessDefinitionId()).singleResult();
            ActReModelFormData actReModelFormData = iActReModelFormDataService.getOne(new QueryWrapper<ActReModelFormData>().eq("process_instance_id", item.getId()));
            Map<String,Object> tempMap = new HashMap<>();

            tempMap.put("modelKey", processDefinition.getKey());
            tempMap.put("modelName", processDefinition.getName());
            tempMap.put("processInstanceId", item.getId());
            tempMap.put("startTime", item.getStartTime());
            if (item.getEndTime() != null) {
                tempMap.put("totalTime", org.jeecg.activiti.util.StringUtils.getTimeDiff(item.getStartTime(), item.getEndTime()));
                tempMap.put("endTime", new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(item.getEndTime()));
            }

            ActHiModelFormData actH = iActHiModelFormDataService.getOne(new QueryWrapper<ActHiModelFormData>()
                    .eq("process_instance_id", item.getId()));
            
            tempMap.put("formId", actH==null?"":actH.getFormId());
            tempMap.put("formDataId", actH==null?"":actH.getId());
            tempMap.put("formData", actH==null?"":actH.getFormData());
            tempMap.put("tableId", actH==null?"":actH.getTableId());
            tempMap.put("tableName", actH==null?"":actH.getTableName());
            tempMap.put("creator", sysUser.getRealname());
            ActReModelExtend modelExtend = actReModelExtendMapper.selectOne(new QueryWrapper<ActReModelExtend>().eq("model_id", actH.getModelId()));
            tempMap.put("reportCode", modelExtend==null?"":modelExtend.getReportCode());
            // 任务名称
            // tempMap.put("instanceName", sysUser.getRealname() + "发起了【" + processDefinition.getName() + "】申请");
            tempMap.put("instanceName", getInstanceName(actReModelFormData));
            tempMap.put("status", actH==null?"":actH.getStatus());
            resultList.add(tempMap);
        });

        return resultList;
    }
    
    @Override
    public List<Map<String, Object>> getAllTask() {
    	
        List<HistoricProcessInstance> historicProcessInstanceList = historyService.createHistoricProcessInstanceQuery()
                .orderByProcessInstanceStartTime().desc().list();

        List<Map<String,Object>> resultList = new ArrayList<>();

        historicProcessInstanceList.forEach(item -> {
            ProcessDefinition processDefinition = repositoryService.createProcessDefinitionQuery().processDefinitionId(item.getProcessDefinitionId()).singleResult();
            ActReModelFormData actReModelFormData = iActReModelFormDataService.getOne(new QueryWrapper<ActReModelFormData>().eq("process_instance_id", item.getId()));
            Task task = taskService.createTaskQuery().processInstanceId(item.getId()).active().singleResult();
            Map<String,Object> tempMap = new HashMap<>();

            tempMap.put("modelKey", processDefinition.getKey());
            tempMap.put("modelName", processDefinition.getName());
            tempMap.put("processInstanceId", item.getId());
            tempMap.put("startTime", item.getStartTime());
            if (item.getEndTime() != null) {
                tempMap.put("totalTime", org.jeecg.activiti.util.StringUtils.getTimeDiff(item.getStartTime(), item.getEndTime()));
                tempMap.put("endTime", new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(item.getEndTime()));
            }

            ActHiModelFormData actH = iActHiModelFormDataService.getOne(new QueryWrapper<ActHiModelFormData>()
                    .eq("process_instance_id", item.getId()));
            LoginUser user = iSysBaseAPI.getUserByUsername(actH.getCreateBy());
            tempMap.put("formId", actH==null?"":actH.getFormId());
            tempMap.put("formDataId", actH==null?"":actH.getId());
            tempMap.put("formData", actH==null?"":actH.getFormData());
            tempMap.put("tableId", actH==null?"":actH.getTableId());
            tempMap.put("tableName", actH==null?"":actH.getTableName());
            tempMap.put("creator", user==null?"":user.getRealname());
            
            // 任务名称
            // tempMap.put("instanceName", user.getRealname() + " 发起了【" + processDefinition.getName() + "】申请");
            tempMap.put("instanceName", getInstanceName(actReModelFormData));
            tempMap.put("status", actH==null?"":actH.getStatus());
            if(task != null){
            	 tempMap.put("taskName", task.getName());
            	 tempMap.put("assignee", task.getAssignee());
            	 tempMap.put("taskId", task.getId());
            }
           
            resultList.add(tempMap);
        });

        return resultList;
    }
    
    @Override
    public IPage<Map<String, Object>> getAllTaskWithPage(String creator, String modelName, String modelKey, Page<Map<String,Object>> page) {
        
        HistoricProcessInstanceQuery query = historyService.createHistoricProcessInstanceQuery();
        if(!StringUtils.isEmpty(creator)){
        	query.startedBy(creator);
        }
        if(!StringUtils.isEmpty(modelName)){
        	query.processDefinitionName(modelName);
        }
        if(!StringUtils.isEmpty(modelKey)){
        	query.processDefinitionKey(modelKey);
        }
        long count = query.count();
        page.setTotal(count);
        List<HistoricProcessInstance> historicProcessInstanceList = query
                .orderByProcessInstanceStartTime().desc().listPage((int)page.offset(), (int)page.getSize());
        List<Map<String,Object>> resultList = new ArrayList<>();

        historicProcessInstanceList.forEach(item -> {
            ProcessDefinition processDefinition = repositoryService.createProcessDefinitionQuery().processDefinitionId(item.getProcessDefinitionId()).singleResult();
            ActReModelFormData actReModelFormData = iActReModelFormDataService.getOne(new QueryWrapper<ActReModelFormData>().eq("process_instance_id", item.getId()));
            
            Map<String,Object> tempMap = new HashMap<>();

            tempMap.put("modelKey", processDefinition.getKey());
            tempMap.put("modelName", processDefinition.getName());
            tempMap.put("processInstanceId", item.getId());
            
            if (item.getEndTime() != null) {
                tempMap.put("totalTime", org.jeecg.activiti.util.StringUtils.getTimeDiff(item.getStartTime(), item.getEndTime()));
                tempMap.put("endTime", new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(item.getEndTime()));
            }
            tempMap.put("startTime", new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(item.getStartTime()));
            ActHiModelFormData actH = iActHiModelFormDataService.getOne(new QueryWrapper<ActHiModelFormData>()
                    .eq("process_instance_id", item.getId()));
            LoginUser user = iSysBaseAPI.getUserByUsername(actH.getCreateBy());
            tempMap.put("formId", actH==null?"":actH.getFormId());
            tempMap.put("formDataId", actH==null?"":actH.getId());
            tempMap.put("formData", actH==null?"":actH.getFormData());
            tempMap.put("tableId", actH==null?"":actH.getTableId());
            tempMap.put("tableName", actH==null?"":actH.getTableName());
            tempMap.put("creator", user==null?"":user.getRealname());
            
            // 任务名称
            // tempMap.put("instanceName", user.getRealname() + " 发起了【" + processDefinition.getName() + "】申请");
            tempMap.put("instanceName", getInstanceName(actReModelFormData));
            tempMap.put("status", actH==null?"":actH.getStatus());
            
            List<Task> tasks = taskService.createTaskQuery().processInstanceId(item.getId()).active().list();
            if(!CollectionUtils.isEmpty(tasks)&&tasks.size() == 1){
            	tempMap.put("taskName", tasks.get(0).getName());
           	 	tempMap.put("assignee", tasks.get(0).getAssignee());
           	 	SysUser sysUser = iSysUserService.getUserByName(tasks.get(0).getAssignee());
           	 	tempMap.put("assigneeName", sysUser == null?"":sysUser.getRealname());
           	 	tempMap.put("taskId", tasks.get(0).getId());
           	 	tempMap.put("multi", 0);
            }else{
            	StringBuffer taskName = new StringBuffer();
            	StringBuffer assignee = new StringBuffer();
            	StringBuffer assigneeName = new StringBuffer();
            	StringBuffer taskId = new StringBuffer();
            	for(Task task : tasks){
            		taskName = taskName.append(task.getName() + ",");
            		assignee = assignee.append(task.getAssignee() + ",");
            		SysUser sysUser = iSysUserService.getUserByName(task.getAssignee());
            		assigneeName = assigneeName.append((sysUser == null?"":sysUser.getRealname()) + ",");
            		taskId = taskId.append(task.getId() + ",");
            	}
            	tempMap.put("taskName", taskName.toString());
           	 	tempMap.put("assignee", assignee.toString());
           	 	tempMap.put("assigneeName", assigneeName.toString());
           	 	tempMap.put("taskId", taskId.toString());
           	 	tempMap.put("multi", 1);
            }
           
            resultList.add(tempMap);
        });
        page.setRecords(resultList);
        return page;
    }
    
    @Override
	public List<Map<String, Object>> getApprovalRecord(String tableId, String dataId) {
    	List<Map<String,Object>> resultList = new ArrayList<>();
    	
    	List<ActReModelFormData> actReModelFormDatas = iActReModelFormDataService.list(new QueryWrapper<ActReModelFormData>().eq("data_id", dataId).orderByDesc("create_time"));
    	if(!CollectionUtils.isEmpty(actReModelFormDatas)){
    		ActReModelFormData actReModelFormData = actReModelFormDatas.get(0);
    		List<HistoricProcessInstance> historicProcessInstanceList = historyService.createHistoricProcessInstanceQuery().processInstanceId(actReModelFormData.getProcessInstanceId()).orderByProcessInstanceStartTime().desc().list();
    		

            historicProcessInstanceList.forEach(item -> {
                ProcessDefinition processDefinition = repositoryService.createProcessDefinitionQuery().processDefinitionId(item.getProcessDefinitionId()).singleResult();
                Map<String,Object> tempMap = new HashMap<>();

                tempMap.put("modelKey", processDefinition.getKey());
                tempMap.put("modelName", processDefinition.getName());
                tempMap.put("processInstanceId", item.getId());
                // tempMap.put("startTime", item.getStartTime());
                if (item.getEndTime() != null) {
                    tempMap.put("totalTime", org.jeecg.activiti.util.StringUtils.getTimeDiff(item.getStartTime(), item.getEndTime()));
                    tempMap.put("endTime", new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(item.getEndTime()));
                }
                tempMap.put("startTime", new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(item.getStartTime()));

                ActHiModelFormData actH = iActHiModelFormDataService.getOne(new QueryWrapper<ActHiModelFormData>()
                        .eq("process_instance_id", item.getId()));
                
                tempMap.put("formId", actH==null?"":actH.getFormId());
                tempMap.put("formDataId", actH==null?"":actH.getId());
                tempMap.put("formData", actH==null?"":actH.getFormData());
                tempMap.put("tableId", actH==null?"":actH.getTableId());
                tempMap.put("tableName", actH==null?"":actH.getTableName());
                tempMap.put("status", actH==null?"":actH.getStatus());
                resultList.add(tempMap);
            });
    	}
    	return resultList;
	}

    @Override
    public Map<String, Object> getNextTaskInfo(String taskId) throws Exception{
        Task task = taskService.createTaskQuery().taskId(taskId).singleResult();
        FlowElement flowElement = getNextUserFlowElement(task);
        UserTask userTask = (UserTask) flowElement;
        Map<String, Object> nextNodeMap = new HashMap<>();
        nextNodeMap.put("name", userTask.getName());

        List<SysUser> sysUsers = new ArrayList<>();

        if (userTask.getAssignee() != null) {
            SysUser sysUser = iSysUserService.getUserByName(userTask.getAssignee());
            sysUsers.add(sysUser);
        } else {
            List<String> candidateUsers = userTask.getCandidateUsers();
            List<String> candidateGroups = userTask.getCandidateGroups();

            if (!CollectionUtils.isEmpty(candidateUsers)) {
                candidateUsers.forEach(item -> {
                    SysUser sysUser = iSysUserService.getUserByName(item);
                    sysUsers.add(sysUser);
                });
            }

            if (!CollectionUtils.isEmpty(candidateGroups)) {
                candidateGroups.forEach(item -> {
                    List<SysUser> users = iSysRoleService.getUsersByRoleCode(item);
                    sysUsers.addAll(users);
                });
            }
        }

        nextNodeMap.put("users", sysUsers);

        return nextNodeMap;
    }

    /**
     * 判断下个节点是否是结束节点
     * @param task
     * @return
     */
    private boolean isEndEvent(Task task, Map<String, Object> transientVariables) {
        //获得当前流程的活动ID
        ExecutionQuery executionQuery = runtimeService.createExecutionQuery();
        Execution execution = executionQuery.executionId(task.getExecutionId()).singleResult();
        String activityId = execution.getActivityId();
        while (true) {
            //根据活动节点获取当前的组件信息
            FlowNode flowNode = getFlowNode(task.getProcessDefinitionId(), activityId);
            if (flowNode != null) {
                //获取该节点之后的流向
                List<SequenceFlow> sequenceFlowListOutGoing = flowNode.getOutgoingFlows();

                // 获取的下个节点不一定是userTask的任务节点，所以要判断是否是任务节点
                if (sequenceFlowListOutGoing.size() > 1) {
                    // 如果有1条以上的出线，表示有分支，需要判断分支的条件才能知道走哪个分支
                    // 遍历节点的出线得到下个activityId
                    activityId = getNextActivityId(execution.getId(),
                            task.getProcessInstanceId(), sequenceFlowListOutGoing, transientVariables);
                } else if (sequenceFlowListOutGoing.size() == 1) {
                    // 只有1条出线,直接取得下个节点
                    SequenceFlow sequenceFlow = sequenceFlowListOutGoing.get(0);
                    // 下个节点
                    FlowElement flowElement = sequenceFlow.getTargetFlowElement();
                    if (flowElement instanceof EndEvent) {
                        return true;
                    } else if (flowElement instanceof ExclusiveGateway) {
                        // 下个节点为排它网关时
                        ExclusiveGateway exclusiveGateway = (ExclusiveGateway) flowElement;
                        List<SequenceFlow> outgoingFlows = exclusiveGateway.getOutgoingFlows();
                        // 遍历网关的出线得到下个activityId
                        activityId = getNextActivityId(execution.getId(), task.getProcessInstanceId(), outgoingFlows, transientVariables);
                    } else {
                        return false;
                    }
                } else {
                    return true;
                }
            } else {
                return false;
            }
        }
    }

    private void handelTaskData(Map<String, Object> tempMap, Task task, ActReModelFormData actReModelFormData, Model model) {
        tempMap.put("modelName", model.getName());
        tempMap.put("modelKey", model.getKey());

        SysUser user = iSysUserService.getUserByName(actReModelFormData.getCreateBy());
       
        if (user != null) {
            tempMap.put("creator", user.getRealname());
            // 任务名称
            //tempMap.put("instanceName", user.getRealname() + "发起了【" + model.getName() + "】申请");
            tempMap.put("instanceName", getInstanceName(actReModelFormData));
        }

        tempMap.put("formDataId", actReModelFormData == null ? "" : actReModelFormData.getId());
        tempMap.put("formId", actReModelFormData.getFormId());

        //任务ID
        tempMap.put("id", task.getId());
        //任务名称
        tempMap.put("name", task.getName());
        // 创建时间
        tempMap.put("createTime", new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(task.getCreateTime()));
        // 任务的办理人
        tempMap.put("assignee", task.getAssignee());
        // 流程实例ID
        tempMap.put("processInstanceId", task.getProcessInstanceId());
        // 执行对象ID
        tempMap.put("executionId", task.getExecutionId());
        // 流程定义ID
        tempMap.put("processDefinitionId", task.getProcessDefinitionId());

        // 父任务ID
        tempMap.put("parentTaskId", task.getParentTaskId());

        // 获取发布的流程节点附加表单
        ActKAppendFormDeployment actKAppendFormDeployment = actKAppendFormDeploymentService.getOne(new LambdaQueryWrapper<ActKAppendFormDeployment>()
                .eq(ActKAppendFormDeployment::getProcessDefinitionId, task.getProcessDefinitionId())
                .eq(ActKAppendFormDeployment::getNodeId, task.getTaskDefinitionKey())
        );
        tempMap.put("appendForm", actKAppendFormDeployment);

        // 查询节点类型
        ActKNode actKNode = iActKNodeService.getOne(new QueryWrapper<ActKNode>()
                .eq("node_id", task.getTaskDefinitionKey()).eq("process_definition_id", task.getProcessDefinitionId()));
        tempMap.put("nodeType", actKNode.getNodeType());
        tempMap.put("nodeId", task.getTaskDefinitionKey());
    }

    /**
     * 获取候选用户任务
     * @return
     */
    private List<Map<String, Object>> getCandidateUserTaskList(String modelKey, String modelName) {
        List<Map<String,Object>> resultList = new ArrayList<>();

        LoginUser sysUser = (LoginUser) SecurityUtils.getSubject().getPrincipal();
        List<String> roles = iSysUserService.getRole(sysUser.getUsername());

        TaskQuery taskQuery = taskService.createTaskQuery();
        taskQuery.taskCandidateUser(sysUser.getUsername(), roles);

        List<Task> tasks =taskQuery.list();

        tasks = tasks.stream().filter(task -> (task.getAssignee() == null)).collect(Collectors.toList());

        tasks.forEach(task -> {
            Map<String,Object> tempMap = new ArrayMap<>();

            // 查询表单数据ID
            ActReModelFormData actReModelFormData = iActReModelFormDataService.getOne(new QueryWrapper<ActReModelFormData>().eq("process_instance_id", task.getProcessInstanceId()));

            // 发起人
            if (actReModelFormData != null) {
                // 流程名称/流程Key
                Model model = repositoryService.createModelQuery().modelId(actReModelFormData.getModelId()).singleResult();

                if (StringUtils.isEmpty(modelKey) && StringUtils.isEmpty(modelName)) {
                    handelGroupTask(tempMap, task, model, actReModelFormData);

                    resultList.add(tempMap);
                } else if (!StringUtils.isEmpty(modelKey) && StringUtils.isEmpty(modelName) && model.getKey().contains(modelKey)) {
                    handelGroupTask(tempMap, task, model, actReModelFormData);

                    resultList.add(tempMap);
                } else if (StringUtils.isEmpty(modelKey) && !StringUtils.isEmpty(modelName) && model.getName().contains(modelName)) {
                    handelGroupTask(tempMap, task, model, actReModelFormData);

                    resultList.add(tempMap);
                } else if (!StringUtils.isEmpty(modelKey) && !StringUtils.isEmpty(modelName)
                        && model.getKey().contains(modelKey)
                        && model.getName().contains(modelName)) {
                    handelGroupTask(tempMap, task, model, actReModelFormData);

                    resultList.add(tempMap);
                }
            }
        });
        return resultList;
    }
    
    // 获取业务标题
    private String getInstanceName(ActReModelFormData actReModelFormData){
    	if(actReModelFormData == null){
    		return "无业务标题";
    	}
    	ActReModelExtend modelExtend = actReModelExtendService.getOne(new QueryWrapper<ActReModelExtend>().eq("model_id", actReModelFormData.getModelId()));
    	Map<String, Object> variables;
        if(actReModelFormData.getTableId() == null){
    		variables = JSONObject.toJavaObject(JSONObject.parseObject(actReModelFormData.getFormData()), Map.class);
        }else{
        	OnlCgformHead head = onlCgformHeadService.getById(actReModelFormData.getTableId());
        	if(head == null){
        		return "无业务标题";
        	}
         	variables = this.fieldService.queryBpmData(actReModelFormData.getTableId(), head.getTableName(), actReModelFormData.getDataId());
         	variables = SqlSymbolUtil.getValueType(variables);
        }
        String expression = modelExtend.getTitle();
        if(StringUtils.isEmpty(expression)){
        	return "无业务标题";
        }
        String title;
        try{
        	title = AviatorEvaluator.execute(expression,variables)+"";
        }catch(Exception e) {
        	log.error("expression========>"+expression);
        	title = "标题加载失败";
        }
        return title;
    }

    private void handelGroupTask(Map<String, Object> tempMap, Task task, Model model, ActReModelFormData actReModelFormData) {
        tempMap.put("modelName", model.getName());
        tempMap.put("modelKey", model.getKey());

        tempMap.put("formDataId", actReModelFormData == null ? "" : actReModelFormData.getId());

        SysUser user = iSysUserService.getUserByName(actReModelFormData.getCreateBy());
        if (user != null) {
            tempMap.put("creator", user.getRealname());
            // 任务名称
            // tempMap.put("instanceName", user.getRealname() + "发起了【" + model.getName() + "】申请");
            tempMap.put("instanceName", getInstanceName(actReModelFormData));
        }

        //任务ID
        tempMap.put("id", task.getId());
        //任务名称
        tempMap.put("name", task.getName());
        // 创建时间
        tempMap.put("createTime", new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(task.getCreateTime()));
        // 任务的办理人
        tempMap.put("assignee", task.getAssignee());
        // 流程实例ID
        tempMap.put("processInstanceId", task.getProcessInstanceId());
        // 执行对象ID
        tempMap.put("executionId", task.getExecutionId());
        // 流程定义ID
        tempMap.put("processDefinitionId", task.getProcessDefinitionId());

        // 父任务ID
        tempMap.put("parentTaskId", task.getParentTaskId());

        // 获取流程节点附加表单
        ActKAppendForm actKAppendForm = iActKAppendFormService.getOne(new QueryWrapper<ActKAppendForm>()
                .eq("node_id", task.getTaskDefinitionKey()));
        tempMap.put("appendForm", actKAppendForm);

        // 查询节点类型
        ActKNode actKNode = iActKNodeService.getOne(new QueryWrapper<ActKNode>()
                .eq("node_id", task.getTaskDefinitionKey()).eq("process_definition_id", task.getProcessDefinitionId()));
        tempMap.put("nodeType", actKNode.getNodeType());
    }

	@Override
	public IPage<ActivitiTaskVo> getMyTaskList(Page<ActivitiTaskVo> page, ActivitiTaskVo activitiTaskVo) {
		List<ActivitiTaskVo> activitiTaskVoList = this.activitiTaskMapper.getMyTaskList(page, activitiTaskVo);
		if(!CollectionUtils.isEmpty(activitiTaskVoList)) {
			for(ActivitiTaskVo ato: activitiTaskVoList) {
				ActKAppendFormDeployment actKAppendFormDeployment = actKAppendFormDeploymentService.getOne(new LambdaQueryWrapper<ActKAppendFormDeployment>()
						.eq(ActKAppendFormDeployment::getProcessDefinitionId, ato.getProcessDefinitionId())
						.eq(ActKAppendFormDeployment::getNodeId, ato.getNodeId()));
				ato.setAppendForm(actKAppendFormDeployment);
				
				ActReModelFormData actReModelFormData = iActReModelFormDataService.getOne(new QueryWrapper<ActReModelFormData>().eq("process_instance_id", ato.getProcessInstanceId()));
				ato.setInstanceName(getInstanceName(actReModelFormData));
			}
		}
		page.setRecords(activitiTaskVoList);
		return page;
	}

	@Override
	public void urging(String procInstId) {
		LoginUser sysUser = (LoginUser) SecurityUtils.getSubject().getPrincipal();

        // 获取当前执行任务节点
        ProcessInstance processInstance = runtimeService.createProcessInstanceQuery().processInstanceId(procInstId).singleResult();
        List<Execution> list = runtimeService.createExecutionQuery().processInstanceId(processInstance.getId()).list();
        Set<Execution> executions = list.stream().filter(execution -> execution.getActivityId() != null).collect(Collectors.toSet());
        ActReModelFormData actReModelFormData = iActReModelFormDataService.getOne(new QueryWrapper<ActReModelFormData>().eq("process_instance_id", procInstId));
        Iterator<Execution> iterator = executions.iterator();
        while (iterator.hasNext()) {
            Execution execution = iterator.next();
            // 获取当前执行任务
            Task task = taskService.createTaskQuery().executionId(execution.getId()).singleResult();
            // String comment = "【" + sysUser.getRealname() + "】催办了【"+ processInstance.getProcessDefinitionName() +"】申请";
            String title = "【催办】"+processInstance.getProcessDefinitionName();
            String content = getInstanceName(actReModelFormData);
            BusMessageDTO msg = new BusMessageDTO();
            msg.setFromUser(sysUser.getUsername());
            msg.setToUser(task.getAssignee());
            msg.setTitle(title);
            msg.setContent(content);
            msg.setCategory("2");
            msg.setBusType("bpm");
            msg.setBusId(task.getId());
            msg.setThirdUrl("/approval");
            iSysBaseAPI.sendBusAnnouncement(msg);
            /*try{
            	WxCpService wxCpService =  WxCpConfiguration.getCpService(agentId);
        		WxCpMessageService wxCpMessageService = new WxCpMessageServiceImpl(wxCpService);
        		String url = wxCpService.getOauth2Service().buildAuthorizationUrl(wxCpService.getWxCpConfigStorage().getDomain()+"/approval",null);
        		LoginUser user = iSysBaseAPI.getUserByName(task.getAssignee());
        		WxCpMessage message = WxCpMessage.TEXTCARD().toUser(user.getThirdId()).agentId(wxCpService.getWxCpConfigStorage().getAgentId()).title(title).description(content).url(url).build();
        		wxCpMessageService.send(message);
            }catch (Exception e) {
			}*/
        }
		
	}

}
